package Entity;

import TileMap.*;


import java.util.ArrayList;
import javax.imageio.ImageIO;
import java.awt.*;
import java.awt.image.BufferedImage;

public class Player extends MapObject {

    // player stuff
    private int health;
    private int maxHealth;
    private int energy;
    private int maxEnergy;
    // energy blast
    private boolean firing;
    private int energyCost;
    private ArrayList<EnergyBlast> energyBlasts;
    // slash
    private boolean slashing;
    // slowfall
    private boolean slowfalling;
    // animations
    private ArrayList<BufferedImage[]> sprites;
    private final int[] numFrames = {
        2, 8, 2, 2, 4, 4, 4,};
    // animation actions
    private static final int IDLE = 0;
    private static final int WALKING = 1;
    private static final int JUMPING = 2;
    private static final int FALLING = 3;
    private static final int SLOWFALLING = 4;
    private static final int ENERGYBLAST = 5;
    private static final int SLASHING = 6;

    public Player(TileMap tm) {

        super(tm);

        width = 30;
        height = 30;
        cwidth = 20;
        cheight = 20;

        moveSpeed = 0.3;
        maxSpeed = 1.6;
        stopSpeed = 0.4;
        fallSpeed = 0.15;
        maxFallSpeed = 4.0;
        jumpStart = -5.9;
        stopJumpSpeed = 0.3;

        facingRight = true;

        health = maxHealth = 30;
        energy = maxEnergy = 201;

        energyCost = 100;

        energyBlasts = new ArrayList<EnergyBlast>();



        // load sprites
        try {

            BufferedImage spritesheet = ImageIO.read(
                    getClass().getResourceAsStream(
                    "/ProjectPictures/zeddPlayerSprites.gif"));

            sprites = new ArrayList<BufferedImage[]>();
            for (int i = 0; i < 7; i++) {

                BufferedImage[] bi =
                        new BufferedImage[numFrames[i]];

                for (int j = 0; j < numFrames[i]; j++) {

                    if (i != SLASHING) {
                        bi[j] = spritesheet.getSubimage(
                                j * width,
                                i * height,
                                width,
                                height);
                    } else {
                        bi[j] = spritesheet.getSubimage(
                                j * width * 2,
                                i * height,
                                width * 2,
                                height);
                    }

                }

                sprites.add(bi);

            }

        } catch (Exception e) {
            e.printStackTrace();
        }

        animation = new Animation();
        currentAction = IDLE;
        animation.setFrames(sprites.get(IDLE));
        animation.setDelay(400);


    }

    public int getHealth() {
        return health;
    }

    public int getMaxHealth() {
        return maxHealth;
    }

    public int getEnergy() {
        return energy;
    }

    public int getMaxEnergy() {
        return maxEnergy;
    }

    public void setFiring() {

        firing = true;

    }

    public void setSlashing() {
        slashing = true;
    }

    public void setSlowFalling(boolean b) {
        slowfalling = b;
    }

    private void getNextPosition() {

        // movement
        if (left) {
            dx -= moveSpeed;
            if (dx < -maxSpeed) {
                dx = -maxSpeed;
            }
        } else if (right) {
            dx += moveSpeed;
            if (dx > maxSpeed) {
                dx = maxSpeed;
            }
        } else {
            if (dx > 0) {
                dx -= stopSpeed;
                if (dx < 0) {
                    dx = 0;
                }
            } else if (dx < 0) {
                dx += stopSpeed;
                if (dx > 0) {
                    dx = 0;
                }
            }
        }

        // jumping
        if (jumping && !falling) {

            dy = jumpStart;
            falling = true;
        }

        // falling
        if (falling) {

            if (dy > 0 && slowfalling) {
                dy += fallSpeed * 0.1;
            } else {
                dy += fallSpeed;
            }

            if (dy > 0) {
                jumping = false;
            }
            if (dy < 0 && !jumping) {
                dy += stopJumpSpeed;
            }

            if (dy > maxFallSpeed) {
                dy = maxFallSpeed;
            }

        }

    }

    public void update() {

        // update position
        getNextPosition();
        checkTileMapCollision();
        setPosition(xtemp, ytemp);

        // check attack has stopped
        if (currentAction == SLASHING || currentAction == ENERGYBLAST) {
            if (animation.hasPlayedOnce()) {
                slashing = false;
            }
        }
        if (currentAction == ENERGYBLAST) {
            if (animation.hasPlayedOnce()) {
                firing = false;
            }
        }

        // fireball attack

        energy += 1;
        if (energy > maxEnergy) {
            energy = maxEnergy;
        }
        if (firing && currentAction != ENERGYBLAST) {


            if (energy > energyCost) {
                energy -= energyCost;
                EnergyBlast fb = new EnergyBlast(tileMap, facingRight);
                fb.setPosition(x, y);
                energyBlasts.add(fb);

            }

        }


        // update fireballs
        for (int i = 0; i < energyBlasts.size(); i++) {
            energyBlasts.get(i).update();
            if (energyBlasts.get(i).shouldRemove()) {
                energyBlasts.remove(i);
                i--;
            }
        }




        // set animation
        if (slashing) {
            if (currentAction != SLASHING) {

                currentAction = SLASHING;
                animation.setFrames(sprites.get(SLASHING));
                animation.setDelay(50);
                width = 60;
            }
        } else if (firing) {
            if (currentAction != ENERGYBLAST) {
                currentAction = ENERGYBLAST;
                animation.setFrames(sprites.get(ENERGYBLAST));
                animation.setDelay(100);
                width = 30;
            }
        } else if (dy > 0) {
            if (slowfalling) {
                if (currentAction != SLOWFALLING) {
                    currentAction = SLOWFALLING;
                    animation.setFrames(sprites.get(SLOWFALLING));
                    animation.setDelay(100);
                    width = 30;
                }
            } else if (currentAction != FALLING) {
                currentAction = FALLING;
                animation.setFrames(sprites.get(FALLING));
                animation.setDelay(100);
                width = 30;
            }
        } else if (dy < 0) {
            if (currentAction != JUMPING) {
                currentAction = JUMPING;
                animation.setFrames(sprites.get(JUMPING));
                animation.setDelay(-1);
                width = 30;
            }
        } else if (left || right) {
            if (currentAction != WALKING) {
                currentAction = WALKING;
                animation.setFrames(sprites.get(WALKING));
                animation.setDelay(40);
                width = 30;
            }
        } else {
            if (currentAction != IDLE) {
                currentAction = IDLE;
                animation.setFrames(sprites.get(IDLE));
                animation.setDelay(400);
                width = 30;
            }
        }

        animation.update();

        // set direction
        if (currentAction != SLASHING && currentAction != ENERGYBLAST) {
            if (right) {
                facingRight = true;
            }
            if (left) {
                facingRight = false;
            }
        }

    }

    public void draw(Graphics2D g) {

        setMapPosition();

        // draw fireballs
        for (int i = 0; i < energyBlasts.size(); i++) {
            energyBlasts.get(i).draw(g);
        }

        // draw player
        super.draw(g);

    }
}
